
//
// 120305 - AH - Created.
//

package org.soekrat.gui.swing.dictionary;

import java.awt.BorderLayout;
import java.util.ArrayList;
import java.util.List;

import javax.swing.DefaultListModel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.ListSelectionModel;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;

import org.soekrat.engine.dictionary.Dictionary;
import org.soekrat.engine.dictionary.SimpleDictionary;

/**
 * <p>
 *   View to select auto completed word in.
 * </p>
 * @author Arne Halvorsen (AH)
 */
@SuppressWarnings("serial")
public final class DictionaryAutoCompleteView extends JPanel 
{
  private transient List<ChangeListener> m_listeners=null;
  
  private final DefaultListModel m_model=new DefaultListModel();
  
  private final JList m_list=new JList(m_model);
  
  private Dictionary m_dict;
  
  /**
   * <p>
   *   Constructor.
   * </p>
   * <p>
   *   Will have a
   *   {@link SimpleDictionary}.
   * </p>
   */
  public DictionaryAutoCompleteView(){ this(null); }
  
  /**
   * <p>
   *   Constructor.
   * </p>
   * @param dict {@link Dictionary} to view, if {@code null} creates a
   *             {@link SimpleDictionary}.
   */
  public DictionaryAutoCompleteView(Dictionary dict)
  {
    m_dict=(dict==null) ? new SimpleDictionary() : dict;
    
    setLayout(new BorderLayout());
    
    m_list.getSelectionModel().setSelectionMode(
      ListSelectionModel.SINGLE_SELECTION);
    
    m_list.addListSelectionListener
    (
      new ListSelectionListener()
      {
        public void valueChanged(ListSelectionEvent e){ fire(); }
      }
    );
    
    add(new JScrollPane(m_list), BorderLayout.CENTER);
  }
  
  /**
   * <p>
   *   Sets dictionary.
   * </p>
   * @param dict {@link Dictionary} or {@code null} if to clear.
   */
  public void setDictionary(Dictionary dict)
  {
    m_model.removeAllElements();
    m_dict=dict;
  }
  
  /**
   * <p>
   *   Gets dictionary.
   * </p>
   * @return {@link Dictionary} or {@code null} if does not have.
   */
  public Dictionary getDictionary(){ return m_dict; }
  
  /**
   * <p>
   *   Gets selected word (prefix+suffix).
   * </p>
   * @return Selected or {@code null} if none selected.
   */
  public String getSelected()
  {
    Object sel=m_list.getSelectedValue();
    return sel==null ? null : sel.toString();
  }
  
  /**
   * <p>
   *   Sets prefix to show suffixes for.
   * </p>
   * @param prefix Prefix.
   */
  public void setPrefix(String prefix)
  {
    if (prefix==null)
    {
      throw new NullPointerException("prefix");
    }
    
    m_model.removeAllElements();
    
    prefix=prefix.trim();
    if (prefix.length()==0) return;
    
    if (m_dict==null) return;
    
    String[] suffixes=m_dict.getSuffixes(prefix);
    
    for (String suffix : suffixes) 
    {
      m_model.addElement(prefix+suffix);  
    }
  }
  
  /**
   * <p>
   *   Adds
   *   {@link ChangeListener}.
   * </p>
   * @param l Listener to add.
   */
  public synchronized void addChangeListener(ChangeListener l)
  {
    if (l==null)
    {
      throw new NullPointerException("l");
    }
    
    if (m_listeners==null) m_listeners=new ArrayList<ChangeListener>();
    if (!m_listeners.contains(l)) m_listeners.add(l);
  }
  
  /**
   * <p>
   *   Removes
   *   {@link ChangeListener}.
   * </p>
   * @param l Listener to remove.
   */
  public synchronized void removeChangeListener(ChangeListener l)
  {
    if (l==null)
    {
      throw new NullPointerException("l");
    }
    
    if (m_listeners==null) return;
    m_listeners.remove(l);
  }
  
  private final static ChangeListener[] E_L_A=new ChangeListener[0];
  
  private final ChangeEvent m_ce=new ChangeEvent(this);
  
  private void fire()
  {
    if (m_listeners==null) return;
    
    ChangeListener[] l=E_L_A;
    synchronized (l){ l=m_listeners.toArray(l); }
    for (ChangeListener curr : l) curr.stateChanged(m_ce);
  }
  
}
